﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public enum GameState
{
    None, Loading, Ready, Running, Pause, End, Setting, Event
}

public enum StateOP
{
    Push, Pop, Load, Next
}

public enum GameScene
{
    Main, Game
}

public abstract class BaseState
{
    public abstract void Enter();
    public abstract void Exit();
    public StateOP state = StateOP.Push;
    public BaseState parent = null;
    public GameScene scene;
}

public class PauseState : BaseState
{
    public override void Enter()
    {
        Time.timeScale = 0;
        Tag.playerPause = true;
    }
    public override void Exit()
    {
        Time.timeScale = 1;
        Tag.playerPause = false;
    }
}

public class EventState : BaseState
{
    public override void Enter()
    {
        Time.timeScale = 0;
        Tag.playerPause = true;
    }
    public override void Exit()
    {
        Time.timeScale = 1;
        Tag.playerPause = false;
    }
}

public class LoadingState : BaseState
{
    public GameState loadState;
    public string load;
    public override void Enter()
    {
        switch(scene)
        {
            case GameScene.Main:
                load = "Main";
                break;
            case GameScene.Game:
                load = "Game";
                break;
            default:
                //Debug.LogError("场景读取错误");
                break;
        }
        //Debug.Log(load);
        SceneManager.LoadScene("Loading", LoadSceneMode.Single);
    }

    public override void Exit()
    {
        GameManager.Instance.DeleteState(GameState.Loading);
    }
}

public class ReadyState : BaseState
{
    public override void Enter()
    {
        //TODO:播放主菜单bgm
    }
    public override void Exit()
    {
        //TODO:退出游戏
    }
}

public class SettingState : BaseState
{
    public override void Enter()
    {
        //TODO:弹出设置菜单
    }
    public override void Exit()
    {
        //TODO:退出设置菜单
    }
}

public class RunningState : BaseState
{
    public override void Enter()
    {
        //TODO:
    }
    public override void Exit()
    {

    }
}

public class EndState : BaseState
{
    public override void Enter()
    {
        Time.timeScale = 0;
        Tag.gameover = true;
        Tag.playerPause = true;
    }
    public override void Exit()
    {
        Time.timeScale = 1;
        Tag.gameover = false;
        Tag.playerPause = false;
    }
}

public class GameManager : MonoBehaviour
{
    public static GameManager Instance
    {
        get
        {
            if (_Instance == null)
            {
                _Instance = FindObjectOfType<GameManager>();
            }
            if (!_Instance)
            {
                GameObject obj = new GameObject("GameManager");
                _Instance = obj.AddComponent<GameManager>();
            }
            return _Instance;
        }
        set
        {
            _Instance = value;
        }
    }
    private static GameManager _Instance;
    
    /*
    MapManager mMapManager = null;
    MouseController mMouseController = null;
    BuildingManager mBuildingManager = null;
    TerrainManager mTerrainManager = null;
    APController mAPController = null;
    MaskManager mMaskManager = null;
    SoldierManager mSoldierManager = null;
    */

    Dictionary<GameState, BaseState> gameStateDict = new Dictionary<GameState, BaseState>();
    public BaseState nowState = null;

    public string SceneName()
    {
        return (nowState as LoadingState).load;
    }

    public BaseState AddState(GameState gs, BaseState bs)
    {
        if(!gameStateDict.ContainsKey(gs))
        {
            gameStateDict[gs] = bs;
            return bs;
        }
        return null;
    }

    public BaseState GetState(GameState gs)
    {
        if (gameStateDict.ContainsKey(gs))
            return gameStateDict[gs];
        return null;
    }

    public bool DeleteState(GameState gs)
    {
        if(gameStateDict.ContainsKey(gs))
        {
            gameStateDict.Remove(gs);
            return true;
        }
        return false;
    }

    public void Restart()
    {
        if (nowState.scene != GameScene.Game)
            return;
        while(nowState != null)
        {
            nowState.Exit();
            nowState = nowState.parent;
        }
        LoadingState loadState = AddState(GameState.Loading, new LoadingState()) as LoadingState;
        //Debug.Log(loadState);
        loadState.loadState = GameState.Running;
        loadState.scene = GetState(GameState.Running).scene;
        loadState.state = StateOP.Load;
        nowState = loadState;
        nowState.Enter();
    }
    
    public void ChangeState(StateOP so, GameState gs = GameState.None)
    {
        BaseState nextState = null;
        switch (so)
        {
            case StateOP.Pop:
                if (gs != GameState.None && GetState(gs) != nowState.parent)
                {
                    Debug.LogError("进入到错误状态");
                    break;
                }
                nowState.Exit();
                nowState = nowState.parent;
                break;
            case StateOP.Push:
                if(gs == GameState.None)
                {
                    Debug.LogError("进入到错误状态");
                    break;
                }
                nextState = GetState(gs);
                if(nextState == null)
                {
                    Debug.LogError("进入到未创建状态");
                    break;
                }
                if(nextState.scene != nowState.scene)
                {
                    while(nowState != null)
                    {
                        nowState.Exit();
                        nowState = nowState.parent;
                    }
                    LoadingState loadState = AddState(GameState.Loading, new LoadingState()) as LoadingState;
                    loadState.loadState = gs;
                    loadState.scene = nextState.scene;
                    loadState.state = StateOP.Load;
                    nowState = loadState;
                    nowState.Enter();
                }
                else
                {
                    if(nextState != nowState)
                    {
                        nextState.parent = nowState;
                        nowState = nextState;
                    }
                    nowState.Enter();
                }
                break;
            case StateOP.Load:
                break;
            case StateOP.Next:
                nowState.Exit();
                nextState = GetState((nowState as LoadingState).loadState);
                nextState.Enter();
                nowState = nextState;
                break;
            default:
                break;
        }
    }

    private void Awake()
    {
        AddState(GameState.Pause, new PauseState()).scene = GameScene.Game;
        AddState(GameState.Ready, new ReadyState()).scene = GameScene.Main;
        AddState(GameState.Setting, new SettingState()).scene = GameScene.Main;
        AddState(GameState.End, new EndState()).scene = GameScene.Game;
        AddState(GameState.Running, new RunningState()).scene = GameScene.Game;
        AddState(GameState.Event, new EventState()).scene = GameScene.Game;
    }

    // Start is called before the first frame update
    void Start()
    {
        DontDestroyOnLoad(gameObject);
        Cursor.lockState = CursorLockMode.Confined;
        nowState = GetState(GameState.Ready);
        nowState.Enter();
        SceneManager.LoadScene("Main", LoadSceneMode.Single);
    }

    Vector3 mousePos;
    // Update is called once per frame
    void Update()
    {
        Vector3 mouseWorldPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
        if (mouseWorldPos != mousePos || Input.GetMouseButtonDown(0))
        {
            mousePos = mouseWorldPos;
            Tag.mouseDelay = 0f;
        }
        else Tag.mouseDelay += 0.016f;
        //Debug.Log(nowState);
        if (nowState.state == StateOP.Load)
        {

        }
        else if(nowState.state == StateOP.Next)
        {
            ChangeState(StateOP.Next);
        }
    }
    
}
